home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Various / DevDisk 65 (1989)(DevWare PD).zip / DevDisk 65 (1989)(DevWare PD).adf / scroll / SD.c < prev    next >
C/C++ Source or Header  |  1990-08-07  |  19KB  |  664 lines

  1. /*------------------------------------------------------------------------*/
  2. /*             Double-Buffered Infinite BitMap Scroll Demo                */
  3. /*           */
  4. /*                   by Mark E. Whitehead   23 SEP 89                   */
  5. /*            */
  6. /*  THIS IS FREELY DISTRIBUTABLE PUBLIC DOMAIN SOFTWARE!              */
  7. /* No charge should be made except for a copying fee.                */
  8. /* If you find a use for this program please give me some            */
  9. /*  credit; otherwise next time all the variable names will           */
  10. /* read something like 'xAcdW3q2'.   Doomo Arigatoo!                 */
  11. /*           */
  12. /*           */
  13. /*      This program demonstrates a double-buffered 'infinite' smooth     */
  14. /* scrolling display using Standard Amiga graphics routines.   It also    */
  15. /* features Simple Sprite animation.  The program creates a randomly      */
  16. /* generated terrain which scrolls from top to bottom.  The user controls */
  17. /* a Spaceship with the joystick while alien 'flying saucers' zig-zag down*/
  18. /* the screen.  The joystick button also launches a missle.  NO collision */
  19. /* detection is performed - that is beyond the scope of this demo. Other  */
  20. /* than that almost everything is here to get you started on your first   */
  21. /* Space Shoot-em-up game!  But first, a word about what we've got to     */
  22. /* work with...                                                           */
  23. /*  The Amiga has built-in hardware scrolling capability but is is not*/
  24. /* practical for large bitmaps since the memory requirements are very     */
  25. /* intensive.  A better method is to scroll the screen using the BLITTER  */
  26. /* and to "update" the graphics in the opposite direction with new data.  */
  27. /* Fortunately, we don't have to mess around with the blitter chip        */
  28. /* directly since SCROLLRASTER() has been provided in ROM. (Thanks!)      */
  29. /* When the screen is scrolled without double-buffering there tends  */
  30. /* to be some separation of the bit planes causing psychodelic colors to  */
  31. /* leak through, as well as a kind of ~~~wave~~~.  Double-buffering stops */
  32. /* this by making sure that all the bit planes have been moved into place */
  33. /* before being displayed.  So there ya go..                              */
  34. /*  In pictorial form here is how the program solves the problem:     */
  35. /*                                                                        */
  36. /*      +-----+-----+-----+-----+ ---------------------                   */
  37. /*      |  a  |  b  |  c  |  d  |  new data buffer    |                   */
  38. /*      |-----+-----+-----+-----| ------------------  |                   */
  39. /*      |  e  |  f  |  g  |  h  |    |                This is one of the  */
  40. /*      |-----+-----+-----+-----|    |                two BitMaps which   */
  41. /*      |     |     |     |     |    |                are alternately     */
  42. /*      |                       |    ViewPort         attached to the     */
  43. /*      ~                       ~    shows this       RastPort            */
  44. /*      ~                       ~    much of Raster   |                   */
  45. /*      |-----------------------|    |                |                   */
  46. /*      |     |     |     |     |    |                |                   */
  47. /*      +-----------------------+  ---------------------                  */
  48. /*                                                                        */
  49. /*  What area of the BitMap (Raster) is defined by the Position of    */
  50. /*  the ViewPort.  In this case it is adjusted down the height of the */
  51. /* terrain blocks.  The letters 'a','b','c' etc. above are block     */
  52. /* shapes which in this program are randomly laid out but can be fed */
  53. /*  in from a pre-defined array!                                      */
  54. /*                                                                        */
  55. /*------------------------------------------------------------------------*/
  56.  
  57. #include <functions.h>
  58. #include <exec/types.h>
  59. #include <exec/memory.h>
  60. #include <intuition/intuition.h>
  61. #include <graphics/sprite.h>
  62. #include <stdio.h>
  63.  
  64. #include "images.c" /* The user defines block shapes in this file */ 
  65.    /* Note ye well that this data is not copied  */
  66.    /* into CHIP memory and thus must be LINKED   */
  67.    /* apropriately such as 'ln +cd scroll' (MANX)*/
  68.  
  69. #include "sprimages.c" /* The user defines sprites in this file */
  70.  
  71. #define ever  (;;)
  72. #define REV  0L
  73. #define abs(x)  ( ((x) < 0) ? -(x) : (x) )
  74.  
  75. #define GROUND  0 /* These are the block shapes which */
  76. #define VOLCANO  1 /* define the terrain piecemeal     */
  77. #define PLANT  2
  78.  
  79. #define NSPRITES 7
  80. #define SPRSIZE  (2L*32L+4L) /* Space for LARGEST Sprite */
  81.  
  82. #define SHIPL  0
  83. #define SHIPR  1 
  84. #define ALIEN0  2
  85. #define ALIEN1  3
  86. #define ALIEN2  4
  87. #define ALIEN3  5
  88. #define MISSILE  6
  89.  
  90. #define TOP  0
  91. #define BOTTOM  200
  92. #define LEFT  10
  93. #define RIGHT  290
  94.  
  95. UWORD colortable[] = {
  96.  0x0000, 0x0ea6, 0x0e93, 0x0e81, /* Background */  
  97.  0x0d70, 0x03a0, 0x0a20, 0x0380, /* Background */
  98.  0x0000, 0x0000, 0x0000, 0x0000, /* Unused     */ 
  99.  0x0000, 0x0000, 0x0000, 0x0000, /* Unused     */
  100.  0x0000, 0x0000, 0x0ccc, 0x0f00, /* Missile    */
  101.  0x0000, 0x0000, 0x088f, 0x052f, /* Ship l & r */
  102.  0x0000, 0x0000, 0x0ccc, 0x0888, /* Aliens     */
  103.  0x0000, 0x0000, 0x0ccc, 0x0888, /* Aliens     */
  104. };
  105.  
  106. #define BLK_W  32 /* Each terrain block is 32 pix wide   */
  107. #define BLK_H  20 /* Each terrain block is 20 pix high   */
  108. #define BLK_D  3 /* Each terrain block is 3 planes deep */
  109. #define N_HBLK  10 /* There are 10 blocks across the scrn */
  110. #define N_VBLK  11 /* There are 10 blocks down the scrn   */
  111.     /* plus one buffer row */ 
  112.  
  113. #define DEPTH   3L   /* 'L' added so I don't */
  114. #define WIDTH   320L   /*  have to cast later..*/
  115. #define HEIGHT   200L   /* Height of Viewport */
  116. #define RHEIGHT  (HEIGHT + (long) BLK_H) /* Height of Raster   */ 
  117.  
  118. struct Screen  *scrn;
  119. struct Window  *win;
  120. struct ViewPort     *vp;
  121. struct RastPort     *rp;
  122. struct  BitMap *bitmap_ptrs[2] = { NULL, NULL }; /* U need this! */  
  123.  
  124. WORD toggle_page = 0;
  125.  
  126. struct Image block = { 0, 0, BLK_W, BLK_H, BLK_D, NULL, 0x7, 0x0, NULL};
  127.  
  128. struct IntuiMessage *msg = NULL;
  129.  
  130. void *GfxBase, *IntuitionBase;
  131.  
  132. struct NewWindow windef = {
  133.  0, 0, WIDTH, 10,
  134.  1, 0,
  135.  CLOSEWINDOW | VANILLAKEY,
  136.  WINDOWCLOSE | BORDERLESS | ACTIVATE,
  137.  NULL, NULL, NULL, NULL, NULL,
  138.  0, 0, 0, 0,
  139.  CUSTOMSCREEN
  140. };
  141.  
  142. struct NewScreen scrndef = {
  143.  0, 0, WIDTH, HEIGHT, DEPTH,
  144.  0, 1,
  145.  SPRITES, 
  146.  CUSTOMSCREEN | CUSTOMBITMAP,
  147.  NULL, NULL, NULL, NULL
  148. };
  149.  
  150. short rowdata[N_HBLK]; /* Store terrain data here for reference */
  151.  
  152. UWORD *sprbuffer = NULL; /* Pointer to CHIP memory buffer we make */
  153.  
  154. struct SimpleSprite shiplspr, shiprspr, mslspr, alienspr[4];
  155.  
  156. short dx[4] = { 2, -1, -2, 1 }, cx[4] = { 40, 50, 20, 100 }, 
  157.  x[4] = { 100, 40, 200, 280 }, y[4] = { 170, 10, 160, 80 },
  158.  sx = 140, sy = 160, mx = 0, my = 200;
  159.  
  160. short fire_cmd = FALSE, misl_on = FALSE;
  161.  
  162.  
  163. /*--------------------- M A I N    R O U T I N E ------------------------*/
  164.  
  165. main()
  166. {
  167.  short i, 
  168.   count = 1, /* Initialize count to 1 for first time    */ 
  169.   pause = TRUE,   /* Let the user read the options first...  */
  170.   tracer = TRUE, /* Toggle Page number text on screen       */
  171.   newrow = FALSE; /* This flag indicates a new row is needed */ 
  172.  
  173.  UBYTE code;
  174.  ULONG class;
  175.  
  176.  openstuff(); /* Open intuition, graphics, screen, window */
  177.  setupsprites();
  178.  
  179.  /* For first pass plaster GROUND terrain across page 0 */
  180.  
  181.  paint_pf();
  182.  pageflip();
  183.  
  184.  /* For first pass plaster GROUND terrain across page 1 */
  185.  
  186.  paint_pf();
  187.  ScrollRaster( rp, 0L, -1L, 0L, 0L, 320L, 219L);  
  188.  pageflip();
  189.  
  190.  /* NOTE: now we have two bitmaps with the same picture; with one */
  191.  /* bitmap exactly ONE row lower than the other.  When we go to   */
  192.  /* scrolling them we will move each exactly TWO rows!  This will */
  193.  /* have the effect of the screen moving only one line at a time  */
  194.  /* when we toggle back and forth.  Think about it for awhile...  */  
  195.  
  196.  for ever {
  197.   
  198.   if (msg = (struct IntuiMessage *) GetMsg(win->UserPort) ) {
  199.    class = msg->Class;
  200.    code  = msg->Code;
  201.    ReplyMsg(msg);
  202.    switch (class) {
  203.    case CLOSEWINDOW: closestuff();
  204.        return;
  205.    case VANILLAKEY:  switch (code) {
  206.        case 'Q': case 'q': 
  207.           closestuff();
  208.           return;
  209.        case 'T': case 't':
  210.           tracer = !tracer;
  211.           break;
  212.        case ' ': pause = !pause;
  213.           break;
  214.        }
  215.    }
  216.   }
  217.  
  218.   if (!pause) {
  219.  
  220.    ScrollRaster( rp, 0L, -2L, 0L, 0L, 320L, 219L);  
  221.  
  222.    if (newrow) {
  223.     draw_new_row();
  224.     newrow = FALSE;
  225.    }
  226.  
  227.    if (++count >= BLK_H) {
  228.     /* This data can come from a pre-defined */
  229.     /*       array just as easily!           */
  230.     for (i=0; i<N_HBLK; i++) 
  231.      rowdata[i] = RangeRand(5L);
  232.     draw_new_row();
  233.     newrow = TRUE;
  234.     count = 0;
  235.    }
  236.  
  237.    for (i=0; i<4; i++) move_aliens( i);
  238.  
  239.    move_ship();
  240.  
  241.    move_missle();
  242.  
  243.    if (tracer)
  244.     switch (toggle_page) {
  245.     case 0: jamit( 10,  218, 1, "Page 0"); break;
  246.     case 1: jamit( 260, 218, 1, "Page 1"); break;
  247.     }
  248.     
  249.    pageflip(); /* Now - FLIP TO THE HIDDEN PAGE! */
  250.  
  251.   }
  252.  }
  253. }
  254.  
  255.  
  256. /*------------------------------------------------------------------------*/
  257. /* Move missle on screen */
  258.  
  259. move_missle()
  260. {
  261.  if (misl_on) {       /* If missle on screen... */
  262.   if ( (my -= 6) <= TOP) { 
  263.    misl_on = FALSE;    /* If at top move offscreen */
  264.    MoveSprite( vp, &mslspr, (long) 0, (long) 200);
  265.   } else        /* Else keep going up */
  266.    MoveSprite( vp, &mslspr, (long) mx, (long) my);
  267.  } else {       /* NOT on screen */ 
  268.   if (fire_cmd) {
  269.    misl_on = TRUE;     /* Put onscreen if commanded */ 
  270.    mx = sx + 14;
  271.    my = sy - 16;
  272.    MoveSprite( vp, &mslspr, (long) mx, (long) my);
  273.   }
  274.  }
  275. }
  276.  
  277.  
  278. /*------------------------------------------------------------------------*/
  279. /* Move Ship under joystick control */
  280.  
  281. move_ship()
  282. {
  283.  short dx = 0, dy = 0;
  284.  
  285.  joystick( &dx, &dy, &fire_cmd);
  286.  
  287.  sx += dx<<1; sy += dy<<1;
  288.  
  289.  if (sx < 10) sx = 10; else if (sx > 280) sx = 280;
  290.  
  291.  if (sy > 160) sy = 160; else if (sy < 10) sy = 10;
  292.  
  293.  MoveSprite( vp, &shiplspr, (long) sx, (long) sy);
  294.  MoveSprite( vp, &shiprspr, (long) sx+16, (long) sy);
  295. }
  296.  
  297.  
  298. /*------------------------------------------------------------------------*/
  299. /* Move Aliens in a zig-zag diving pattern */
  300.  
  301. move_aliens(i)
  302. short i;
  303. {
  304.  if (--(cx[i]) < 0) {
  305.   cx[i] = 50 + RangeRand(100L); /* New charge duration */ 
  306.   dx[i] = -dx[i];   /* Go the other way... */
  307.  }
  308.  
  309.  if ( cx[i] < 15)
  310.   y[i] += 3;
  311.  else
  312.   if ( cx[i] < 40)
  313.    y[i] += 2;
  314.   else
  315.    ++(y[i]);
  316.  
  317.  if ( y[i] > BOTTOM) {
  318.   y[i] = TOP;   /* Re-position at top */
  319.   x[i]  = 50 + RangeRand(200L); /* New starting x pos */
  320.  }
  321.  
  322.  x[i] += dx[i]; 
  323.  
  324.  if ( x[i] < LEFT || x[i] > RIGHT) dx[i] = -dx[i];
  325.  
  326.  MoveSprite( vp, &alienspr[i], (long) x[i], (long) y[i]);
  327. }
  328.  
  329.  
  330. /*-------------------------------------------------------------------------*/
  331. /* Do Page Flipping - From ROM Kernal Manual BOB example */
  332.  
  333. pageflip()
  334. {
  335.  scrn->ViewPort.RasInfo->BitMap = bitmap_ptrs[toggle_page];
  336.  WaitTOF();
  337.  MakeScreen(scrn);
  338.  RethinkDisplay();
  339.  toggle_page ^=1;
  340.  scrn->RastPort.BitMap = bitmap_ptrs[toggle_page];
  341. }
  342.  
  343.  
  344. /*-------------------------------------------------------------------------*/
  345. /* New Terrain */
  346.  
  347. draw_new_row()
  348. {
  349.  short i, x;
  350.  UWORD *image;
  351.  
  352.  for (i=0, x=0; i<N_HBLK; i++, x+=BLK_W) {
  353.   switch ( rowdata[i] ) {
  354.    case GROUND:  image = ground;  break;
  355.    case VOLCANO: image = volcano; break;
  356.    case PLANT:   image = plant;   break;
  357.    default:      image = ground; break;
  358.   }
  359.   drawblock( image, x, toggle_page);
  360.  }
  361. }
  362.  
  363.  
  364.  
  365. /*-------------------------------------------------------------------------*/
  366. /* Paint playfield */
  367.  
  368. paint_pf()
  369. {
  370.  short i, j, x, y;
  371.  
  372.  for (j=0, y=0; j<N_VBLK; j++, y+=BLK_H)
  373.   for (i=0, x=0; i<N_HBLK; i++, x+=BLK_W)
  374.    drawblock( &ground, x, y);
  375.  
  376.  shadow( 35, 70, 6, "Double-Buffered Infinite BitMap");
  377.  shadow( 35, 80, 6, " Scroll Demonstration Program");
  378.  shadow( 35, 90, 6, "by Mark Edward Whitehead  1989");
  379.  
  380.  shadow( 50, 130, 7, "Joystick Controls SpaceShip");
  381.  shadow( 50, 140, 7, "Spacebar will STOP/START Scroll");
  382.  shadow( 50, 150, 7, "T toggles Page Flip display");
  383.  shadow( 50, 160, 7, "Q quits Demonstration");
  384. }
  385.  
  386.  
  387. /*-------------------------------------------------------------------------*/
  388. /* Draw a block on screen */
  389.  
  390. drawblock( p, x, y)
  391. UWORD *p;
  392. short x, y;
  393. {
  394.  block.LeftEdge = x;
  395.  block.TopEdge = y;
  396.  block.ImageData = p;
  397.  DrawImage( rp, &block, 0L, 0L);
  398. }
  399.  
  400.  
  401. /*-------------------------------------------------------------------------*/
  402. /* Set up the sprites.  This routine and it's support routines take the    */
  403. /* hassle out of using Sprites.  What I do is create a buffer which is     */
  404. /* partitioned into areas the size of the largest Sprite and has big as    */
  405. /* the number of Sprite shapes I'm going to need.  Then the data is copied */
  406. /* into this CHIP buffer.  Now I can quickly calculate the offset into the */
  407. /* buffer to change my sprite shapes.  MEW                                 */ 
  408.  
  409. setupsprites()
  410. {
  411.  if (!(sprbuffer = AllocMem( (long) 2*SPRSIZE*NSPRITES, MEMF_CHIP) ))
  412.   die("No memory for sprite data.");
  413.  
  414.  add_spr( SHIPL, shipl);
  415.  add_spr( SHIPR, shipr);
  416.  
  417.  add_spr( ALIEN0, alien);
  418.  add_spr( ALIEN1, alien);
  419.  
  420.  add_spr( ALIEN2, alien);
  421.  add_spr( ALIEN3, alien);
  422.  
  423.  add_spr( MISSILE, missile);
  424.  
  425.  init_sprite( &shiplspr, SHIPL, 2, sx, sy, 32);
  426.  init_sprite( &shiprspr, SHIPR, 3, sx+16, sy, 32);
  427.  
  428.  init_sprite( &alienspr[0], ALIEN0, 6, x[0], y[0], 15);
  429.  init_sprite( &alienspr[1], ALIEN1, 7, x[1], y[1], 15);
  430.  init_sprite( &alienspr[2], ALIEN2, 4, x[2], y[2], 15);
  431.  init_sprite( &alienspr[3], ALIEN3, 5, x[3], y[3], 15);
  432.  
  433.  init_sprite( &mslspr, MISSILE, 1, mx, my, 15);
  434. }
  435.  
  436.  
  437. /*-------------------------------------------------------------------------*/
  438. /* Initialize a sprite */
  439.  
  440. init_sprite( s, shpnum, n, x, y, h)
  441. struct SimpleSprite *s;
  442. short shpnum, n, x, y, h;
  443. {
  444.  if ( GetSprite( s, (long) n) < 0 ) die("Sprite not available.");
  445.  
  446.  s->x = x;
  447.  s->y = y;
  448.  s->height = h;
  449.  
  450.  ChangeSprite( vp, s, sprbuffer + shpnum * SPRSIZE);
  451. }
  452.  
  453.  
  454. /*-------------------------------------------------------------------------*/
  455. /* Add a sprite data to the CHIP ram buffer. SPRSIZE is the largest spr    */
  456.  
  457. add_spr( n, src)
  458. UWORD n, *src;
  459. {
  460.  short i;
  461.  UWORD *buffer;
  462.  
  463.  buffer = sprbuffer +  n * SPRSIZE;
  464.  
  465.  for (i=0; i<SPRSIZE; i++) *buffer++ = *src++;
  466. }
  467.  
  468.  
  469. /*-------------------------------------------------------------------------*/
  470. /* Get memory for a double buffered bit map */
  471.  
  472. get_bitmaps()
  473. {
  474.  short i, j;
  475.  
  476.  for(j=0; j<2; j++) {
  477.   if ((bitmap_ptrs[j] = AllocMem( (long) sizeof(struct BitMap), MEMF_CHIP)) == 0) 
  478.     die("Can't get bitmap memory");
  479.  
  480.   InitBitMap(bitmap_ptrs[j], DEPTH, WIDTH, RHEIGHT);
  481.  
  482.   for(i=0; i<DEPTH; i++) {
  483.  
  484.    if ((bitmap_ptrs[j]->Planes[i] = (PLANEPTR)
  485.     AllocRaster(WIDTH, RHEIGHT)) == 0)
  486.      die("Can't get bitmap planes");
  487.  
  488.    BltClear(bitmap_ptrs[j]->Planes[i],(long) (WIDTH/8)*RHEIGHT, 1L);
  489.   }
  490.  }
  491. }
  492.  
  493.  
  494. /*-------------------------------------------------------------------------*/
  495. /* Free memory for a double buffered bit map */
  496.  
  497. free_bitmaps()
  498. {
  499.  short i, j;
  500.  
  501.  for (j=0; j<2; j++) {
  502.   if (bitmap_ptrs[j]) {
  503.    for (i=0; i<DEPTH; i++) {
  504.    if (bitmap_ptrs[j]->Planes[i] != 0)
  505.     FreeRaster(bitmap_ptrs[j]->Planes[i], WIDTH, RHEIGHT);
  506.    }
  507.   FreeMem(bitmap_ptrs[j], (long) sizeof(struct BitMap));
  508.   } 
  509.  }
  510. }
  511.  
  512.  
  513. /*-------------------------------------------------------------------------*/
  514. /* Print drop-shadow text to rastport */
  515.  
  516. shadow( x, y, color, txt)
  517. short x, y, color;
  518. char *txt;
  519. {
  520.  SetDrMd( rp, (long) JAM1);
  521.  
  522.  SetAPen( rp, (long) 0L);
  523.  Move( rp, (long) x-1, (long) y+1);
  524.  Text( rp, (long) txt, (long) strlen(txt) );
  525.  
  526.  SetAPen( rp, (long) color);
  527.  Move( rp, (long) x, (long) y);
  528.  Text( rp, (long) txt, (long) strlen(txt) );
  529. }
  530.  
  531.  
  532. /*-------------------------------------------------------------------------*/
  533. /* Jam those colors into the display */
  534.  
  535. jamit( x, y, color, txt)
  536. short x, y, color;
  537. char *txt;
  538. {
  539.  SetDrMd( rp, (long) JAM2);
  540.  SetBPen( rp, (long) 0);
  541.  SetAPen( rp, (long) color);
  542.  Move( rp, (long) x, (long) y);
  543.  Text( rp, (long) txt, (long) strlen(txt) );
  544. }
  545.  
  546.  
  547. /*-------------------------------------------------------------------------*/
  548. /* Read joystick hardware directly and return delta x, delta y and fire    */
  549. /* button discrete.  Note that this routine bypasses normal i/o functions  */
  550. /* so that any screen blanker program, for example, won't hear about it... */
  551.  
  552. joystick( dx, dy, fire)
  553. USHORT *dx, *dy, *fire;
  554. {
  555.  USHORT *joy = (USHORT *) 0xdff00c;
  556.  USHORT *button = (USHORT *) 0xbfe0fe;
  557.  USHORT sample;
  558.  
  559.  sample = *joy & 771; /* Mask off Non-Joystick bits */
  560.  
  561.  switch (sample) {
  562.   case 0:  *dx = 0; *dy = 0; break; /* Center      */
  563.   case 1:  ++(*dy); break;   /* Down        */
  564.   case 2:  ++(*dy); ++(*dx); break; /* Down, Right */
  565.   case 3:  ++(*dx); break;   /* Right       */
  566.   case 256: --(*dy); break;   /* Up          */
  567.   case 259: --(*dy); ++(*dx); break; /* Up, Right   */
  568.   case 512: --(*dy); --(*dx); break; /* Up, Left    */
  569.   case 768: --(*dx); break;     /* Left        */
  570.   case 769: ++(*dy); --(*dx); break; /* Down, Left  */
  571.   default: *dx = 0; *dy = 0;
  572.  }
  573.  
  574.  if ( !(*button & 0x0080) )  *fire = TRUE; else *fire = FALSE;
  575. }
  576.  
  577.  
  578. /*-------------------------------------------------------------------------*/
  579. /* Open up system libraries and stuff */
  580.  
  581. openstuff()
  582. {
  583.  if (!(IntuitionBase = OpenLibrary ("intuition.library", REV)))
  584.   die ("Intuition doesn't 'open up' to me.");
  585.  
  586.  if (!(GfxBase = OpenLibrary ("graphics.library", REV)))
  587.   die ("Art shop closed.");
  588.  
  589.  get_bitmaps();  /* Allocate custom bitmaps for dbuf */
  590.  
  591.  scrndef.CustomBitMap = bitmap_ptrs[0];
  592.  scrn->RastPort.Flags = DBUFFER;
  593.  
  594.  if (!(scrn = OpenScreen (&scrndef)))
  595.   die ("Screen painted shut.");
  596.  
  597.  windef.Screen = scrn;
  598.  
  599.  if (!(win = OpenWindow( &windef)))
  600.   die ("Window stuck tight.");
  601.  
  602.  vp  = &(scrn -> ViewPort);
  603.  rp  = &(scrn -> RastPort);
  604.  
  605.  LoadRGB4( vp, colortable, 32L);
  606.  
  607.  /* Make the screen using pointer to bitmap 0 */
  608.  
  609.  scrn->ViewPort.RasInfo->BitMap = bitmap_ptrs[0];
  610.  scrn->ViewPort.RasInfo->RyOffset = BLK_H;
  611.  MakeScreen(scrn);
  612.  RethinkDisplay();
  613. }
  614.  
  615.  
  616. /*-------------------------------------------------------------------------*/
  617. /* Close what we opened, deallocate what we allocated */
  618.  
  619. closestuff()
  620. {
  621.  if (sprbuffer)
  622.   FreeMem( sprbuffer, (long) 2*SPRSIZE*NSPRITES);
  623.  
  624.  if (shiplspr.num) 
  625.   FreeSprite( (long) shiplspr.num );
  626.  if (shiprspr.num) 
  627.   FreeSprite( (long) shiprspr.num );
  628.  if (alienspr[0].num) 
  629.   FreeSprite( (long) alienspr[0].num );
  630.  if (alienspr[1].num) 
  631.   FreeSprite( (long) alienspr[1].num );
  632.  if (alienspr[2].num) 
  633.   FreeSprite( (long) alienspr[2].num );
  634.  if (alienspr[3].num) 
  635.   FreeSprite( (long) alienspr[3].num );
  636.  if (mslspr.num) 
  637.   FreeSprite( (long) mslspr.num );
  638.  
  639.  if (win)
  640.   CloseWindow(win);
  641.  if (scrn)
  642.   CloseScreen(scrn);
  643.  
  644.  free_bitmaps();  /* This must be done AFTER screen closed */
  645.  
  646.  if (GfxBase)
  647.   CloseLibrary (GfxBase);
  648.  if (IntuitionBase)
  649.   CloseLibrary (IntuitionBase);
  650. }
  651.  
  652.  
  653. /*-------------------------------------------------------------------------*/
  654. /* Post a complaint on the way out */
  655.  
  656. die(str)
  657. char *str;
  658. {
  659.  puts(str);
  660.  closestuff();
  661.  exit (-1);
  662. }
  663.  
  664.